
#if defined(TSINGMA_MX) || defined(TSINGMA_GX)
/**
 @file sys_tmm_packet.c

 @author  Copyright (C) 2020 Centec Networks Inc.  All rights reserved.

 @date 2020-04-20

 @version v1.0

*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_crc.h"
#include "ctc_packet.h"
#include "sys_usw_dma.h"
#include "sys_usw_common.h"
#include "sys_usw_register.h"
#include "sys_usw_chip.h"
#include "sys_usw_port_api.h"
#include "sys_usw_dma.h"
#include "sys_usw_packet.h"
#include "sys_usw_eunit.h"
#include "../sys_usw_packet_priv.h"
#include "usw/include/drv_common.h"

#include "drv_api.h"

/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
extern sys_pkt_master_t* p_usw_pkt_master[];

#define SYS_PKT_OAM_VRF_VALID (1<<14)
/****************************************************************************
 *
* Functions
*
****************************************************************************/
extern int32
_sys_usw_packet_get_svlan_tpid_index(uint8 lchip, uint16 svlan_tpid, uint8* svlan_tpid_index, sys_pkt_tx_hdr_info_t* p_tx_hdr_info);
extern int32
_sys_usw_packet_ts_to_bit62(uint8 lchip, uint32 ns_only_format, ctc_packet_ts_t* p_ts, uint64* p_ts_61_0);
extern int32
_sys_usw_packet_bit62_to_ts(uint8 lchip, uint32 ns_only_format, uint64 ts_61_0, ctc_packet_ts_t* p_ts);
extern int32
_sys_usw_packet_recover_timestamp(uint8 lchip, uint32 ts_36_5, uint64* p_ts_61_0);

/**
   CTC_PKT_DIS_TS [rx/tx] : disable packet process timestamp and ptp info
   CTC_PKT_DIS_OAM[rx/tx] : disable packet process oam info, not support oam packet
   CTC_PKT_DIS_STK[rx/tx] : disable packet process stacking info

*/
int32
sys_tmm_packet_txinfo_to_rawhdr(uint8 lchip, ctc_pkt_tx_t* p_pkt_tx)
{
    ms_packet_header_tmm_t* p_raw_hdr = NULL;
    ms_packet_header_tmm_tail_t* p_raw_hdr_tail;
    ctc_pkt_info_t* p_tx_info = NULL;
    uint32* p_raw_hdr_net = NULL;
    uint32 tmp_raw_hdr[CTC_PKT_HDR_ROOM/sizeof(uint32)] = {0};
    uint32 dest_map                = 0;
    uint16 vlan_ptr                = 0;
    uint8 gchip                    = 0;
    uint32 lport                   = 0;
    uint8 hash                     = 0;
    uint8 src_gchip                = 0;
    uint8 packet_type              = 0;
    uint8 priority                 = 0;
    uint8 color                    = 0;
    uint32 src_port                = 0;
    uint32 next_hop_ptr            = 0;
    uint32 ts_36_5 = 0;
    uint32 ts_4_0 = 0;
    uint32 ts_61_37 = 0;
    uint64 ts_61_0 = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
    uint64 offset = 0;
    uint8  svlan_tpid_index = 0;
    uint32  chan_id = SYS_DMPS_INVALID_CHAN_ID;
    sys_nh_info_dsnh_t      sys_nh_info;
    uint32 gport = 0;
    bool* p_protect_en = NULL;
    bool protect_en = FALSE;
    uint32 mep_index = 0;
    uint16 sub_queue_id = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    
    p_tx_info = &p_pkt_tx->tx_info;
    p_raw_hdr_net = (uint32*)p_pkt_tx->skb.head;
    sal_memset(tmp_raw_hdr, 0, SYS_USW_PKT_HEADER_LEN);

    /* zero copy mode, p_raw_hdr_net is dma memory, use temp variable to reduce times of accessing dma memory */
    p_raw_hdr = (ms_packet_header_tmm_t*)&tmp_raw_hdr;
    p_raw_hdr_tail = (ms_packet_header_tmm_tail_t*)(&tmp_raw_hdr[10]);/* header tail is after header, head length is 40B */

    /* Must be inited */
    p_raw_hdr->packet_type = p_tx_info->packet_type;
    /* Support offload data tunnel cryption in hw */
    p_raw_hdr->packet_offset = p_tx_info->payload_offset;

        p_raw_hdr->from_cpu_or_oam = 1;
    p_raw_hdr->operation_type = p_tx_info->oper_type;
    p_raw_hdr->critical_packet = p_tx_info->is_critical;
    p_raw_hdr->src_stag_cos = p_tx_info->src_cos;
    p_raw_hdr->ttl = p_tx_info->ttl;
    p_raw_hdr->mac_known = CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_UNKOWN_MACDA)?0:1;
    p_raw_hdr->fid = p_tx_info->fid;
    CTC_ERROR_RETURN(_sys_usw_packet_get_svlan_tpid_index(lchip, p_tx_info->svlan_tpid, &svlan_tpid_index, &p_usw_pkt_master[lchip]->tx_hdr_info));
    p_raw_hdr->svlan_tpid_index = svlan_tpid_index;

    p_raw_hdr->from_cpu = 1;
    p_raw_hdr->logic_src_port_15_8_0 = p_tx_info->logic_src_port&0x1FF;
    p_raw_hdr->logic_src_port_15_14_9 = (p_tx_info->logic_src_port>>9)&0x3F;
    p_raw_hdr->logic_port_type = p_tx_info->logic_port_type;
    p_raw_hdr->local_phy_port = p_tx_info->lport;

    if(p_tx_info->cid)
    {
       p_raw_hdr->u1.normal.i2e_src_cid = p_tx_info->cid & 0xFF;
       p_raw_hdr->u1.normal.i2e_src_cid_valid = 1;
    }
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_DIAG_PKT))
    {
        p_raw_hdr->is_debugged_pkt = 1;
        p_raw_hdr_tail->is_sniffing_packet = 1;
    }

    /*don't eccrypt specified pkt*/
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_CANCEL_DOT1AE))
    {
        p_raw_hdr_tail->bypass_macsec_proc = 1;
    }

    /*Set oamuse fid lookup */
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_OAM_USE_FID))
    {
        p_raw_hdr->oam_use_fid = 1;
    }

   /*Set Vlan domain */
    if (p_tx_info->vlan_domain == CTC_PORT_VLAN_DOMAIN_SVLAN)
    {
        p_raw_hdr->outer_vlan_is_cvlan = 0;
        /*sys_usw_vlan_get_vlan_ptr(lchip, p_tx_info->src_svid, &vlan_ptr);*/
        vlan_ptr = p_usw_pkt_master[lchip]->tx_hdr_info.vlanptr[p_tx_info->src_svid];
        p_raw_hdr->src_vlan_ptr_14_0_0 = vlan_ptr&0x1;
        p_raw_hdr->src_vlan_ptr_14_13_1 = (vlan_ptr>>1)&0x1FFF;
    }
    else  if (p_tx_info->vlan_domain == CTC_PORT_VLAN_DOMAIN_CVLAN)
    {
        p_raw_hdr->outer_vlan_is_cvlan = 1;
        /*sys_usw_vlan_get_vlan_ptr(lchip, p_tx_info->src_cvid, &vlan_ptr);*/
        vlan_ptr = p_usw_pkt_master[lchip]->tx_hdr_info.vlanptr[p_tx_info->src_cvid];
        p_raw_hdr->src_vlan_ptr_14_0_0 = vlan_ptr&0x1;
        p_raw_hdr->src_vlan_ptr_14_13_1 = (vlan_ptr>>1)&0x1FFF;
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    /* Next_hop_ptr and DestMap*/
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_BPE_TRANSPARENT))
    {
        /* Bypass NH is 8W  and egress edit mode*/
        p_raw_hdr->bypass_ingress_edit = 1;
        p_raw_hdr->next_hop_ext = 1;
        /*CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_BPE_TRANSPARENT_NH, &next_hop_ptr));*/
        next_hop_ptr = p_usw_pkt_master[lchip]->tx_hdr_info.rsv_nh[SYS_NH_RES_OFFSET_TYPE_BPE_TRANSPARENT_NH];
    }
    else if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_NH_OFFSET_BYPASS))
    {
        /* Bypass NH is 8W  and egress edit mode*/
        p_raw_hdr->bypass_ingress_edit = 1;
        p_raw_hdr->next_hop_ext = 1;
        /*CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_BYPASS_NH, &next_hop_ptr));*/
        next_hop_ptr = p_usw_pkt_master[lchip]->tx_hdr_info.rsv_nh[SYS_NH_RES_OFFSET_TYPE_BYPASS_NH];
    }
    else
    {
        if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_NH_OFFSET_VALID))
        {
            next_hop_ptr = p_tx_info->nh_offset;
            if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_NH_OFFSET_IS_8W))
            {
                p_raw_hdr->next_hop_ext = 1;
            }
        }
        else
        {
            /* GG Bridge NH is 4W */
            p_raw_hdr->next_hop_ext = 0;
            /*CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH, &next_hop_ptr));*/
            next_hop_ptr = p_usw_pkt_master[lchip]->tx_hdr_info.rsv_nh[SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH];
        }
    }

    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_MCAST))
    {
        dest_map = SYS_ENCODE_MCAST_IPE_DESTMAP(p_tx_info->dest_group_id);
        next_hop_ptr = 0;
    }
    else
    {
        if (CTC_IS_LINKAGG_PORT(p_tx_info->dest_gport))
        {
            dest_map = SYS_ENCODE_DESTMAP(CTC_LINKAGG_CHIPID, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_tx_info->dest_gport));
        }
        else
        {
            gchip = CTC_MAP_GPORT_TO_GCHIP(p_tx_info->dest_gport);
            if (CTC_IS_CPU_PORT(p_tx_info->dest_gport))
            {
                /*CTC_ERROR_RETURN(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_FWD_CPU, &sub_queue_id));*/
                sub_queue_id = p_usw_pkt_master[lchip]->tx_hdr_info.fwd_cpu_sub_queue_id;
                dest_map = SYS_ENCODE_EXCP_DESTMAP(gchip, sub_queue_id);
            }
            else
            {
                dest_map = SYS_ENCODE_DESTMAP(gchip, SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_tx_info->dest_gport));
            }
        }
    }

    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_NHID_VALID))
    {
        sal_memset(&sys_nh_info, 0, sizeof(sys_nh_info_dsnh_t));
        if(CTC_E_NONE == sys_usw_nh_get_nhinfo(lchip, p_tx_info->nhid, &sys_nh_info, 1))
        {
            next_hop_ptr = sys_nh_info.dsnh_offset;
            p_raw_hdr->next_hop_ext = sys_nh_info.nexthop_ext;
            dest_map = sys_nh_info.dest_map;

            if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_ASSIGN_DEST_PORT))
            {
                sys_usw_get_gchip_id(lchip, &gchip);
                dest_map = SYS_ENCODE_DESTMAP(gchip, p_tx_info->lport);
            }

            if(sys_nh_info.aps_en)
            {
                if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_APS_PATH_EN))
                {
                    mep_index = p_tx_info->aps_p_path ? 0x3 : 0x1;
                    protect_en = p_tx_info->aps_p_path;
                    p_protect_en = &protect_en;
                    if (!sys_nh_info.mep_on_tunnel)
                    {
                        mep_index = 0;
                    }
                }

                CTC_ERROR_RETURN(sys_usw_nh_get_aps_working_path(lchip, p_tx_info->nhid, &gport, &next_hop_ptr, p_protect_en));
                dest_map = SYS_ENCODE_DESTMAP(SYS_MAP_CTC_GPORT_TO_GCHIP(gport), SYS_MAP_CTC_GPORT_TO_DRV_LPORT(gport));
            }
        }
        p_raw_hdr->bypass_ingress_edit = sys_nh_info.bypass_igr_edit;
    }

    p_raw_hdr->next_hop_ptr_18_0_0 = next_hop_ptr&0x1;
    p_raw_hdr->next_hop_ptr_18_17_1 = (next_hop_ptr>>1)&0x1FFFF;
    p_tx_info->nh_offset = next_hop_ptr;

    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_ASSIGN_DEST_PORT) && !(CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_NHID_VALID)))
    {
        uint8 gchip = 0;

        sys_usw_get_gchip_id(lchip, &gchip);
        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, p_tx_info->lport);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
        if(SYS_COMMON_USELESS_CHANNEL != chan_id)
        {
            p_raw_hdr_tail->dest_channel_id_from_cpu = chan_id;
            p_raw_hdr_tail->dest_channel_id_valid_from_cpu = 1;
        }
    }

    /* SrcPort */
    sys_usw_get_gchip_id(lchip, &src_gchip);
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_SRC_PORT_VALID))
    {
        src_port = p_tx_info->src_port;
        if(CTC_IS_LINKAGG_PORT(p_tx_info->src_port))
        {
            p_raw_hdr->from_lag = 1;
            src_port = CTC_MAP_LPORT_TO_GPORT(src_gchip, CTC_MAP_GPORT_TO_LPORT(src_port));
        }
        else if (CTC_IS_CPU_PORT(p_tx_info->src_port))
        {
           src_port = CTC_MAP_LPORT_TO_GPORT(src_gchip, SYS_RSV_PORT_OAM_CPU_ID);
        }
    }
    else
    {
        src_port = CTC_MAP_LPORT_TO_GPORT(src_gchip, SYS_RSV_PORT_OAM_CPU_ID);
    }
    src_port = SYS_MAP_CTC_GPORT_TO_DRV_GPORT(src_port);
    p_raw_hdr->source_port_16_0_0 = src_port&0x1;
    p_raw_hdr->source_port_16_15_1 = (src_port>>1)&0x7FFF;

    /* Svid */
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_SRC_SVID_VALID))
    {
        p_raw_hdr->src_svlan_id = p_tx_info->src_svid;
        p_raw_hdr->stag_action = DRV_ENUM(DRV_VTAGACTIONTYPE_ADD);
        p_raw_hdr->svlan_tag_operation_valid = 1;
    }

    /* Cvid */
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_SRC_CVID_VALID))
    {
        p_raw_hdr->u1.normal.src_cvlan_id = p_tx_info->src_cvid;
        p_raw_hdr->u1.normal.ctag_action = DRV_ENUM(DRV_VTAGACTIONTYPE_ADD);
        p_raw_hdr->u1.normal.cvlan_tag_operation_valid = 1;
    }

    /* isolated_id*/
    if (0 != p_tx_info->isolated_id)
    {
        p_raw_hdr->u1.normal.source_port_isolateId = p_tx_info->isolated_id;
    }

    /* Linkagg Hash*/
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_HASH_VALID))
    {
        hash = p_tx_info->hash;
    }
    else
    {
        hash = ctc_crc_calculate_crc8(p_pkt_tx->skb.data, 12, 0);
    }
    p_raw_hdr->header_hash = hash;

    /* PHB priority + color */
    priority = (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_PRIORITY)) ? p_tx_info->priority : SYS_PACKET_TX_MAX_PRIORITY;
    color = (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_COLOR)) ? p_tx_info->color : CTC_QOS_COLOR_GREEN;
    p_raw_hdr->color = color;

    /* Iloop */
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_INGRESS_MODE))
    {
        gchip = CTC_MAP_GPORT_TO_GCHIP(p_tx_info->dest_gport);
        lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_tx_info->dest_gport);
        /* dest_map is ILOOP */
        dest_map = SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_ILOOP_ID);
        dest_map = dest_map | (lport&0x100); /*sliceId*/
        p_raw_hdr->dest_map = dest_map;

        /* nexthop_ptr is lport */
        next_hop_ptr = SYS_PACKET_ENCAP_LOOP_NHPTR(lport, 0);
        p_raw_hdr->next_hop_ptr_18_0_0 = next_hop_ptr&0x1;
        p_raw_hdr->next_hop_ptr_18_17_1 = (next_hop_ptr>>1)&0x1FFFF;
    }
    else
    {
        p_raw_hdr->bypass_ipe = 1;
    }

    /* OAM Operation*/
    if (CTC_PKT_OPER_OAM == p_tx_info->oper_type)
    {
        p_raw_hdr->u1.oam.mep_index = mep_index;
        if (p_tx_info->src_cos)
        {
            p_raw_hdr->u1.oam.mep_index |= (1<<3);
        }

        p_raw_hdr->u1.oam.oam_type = p_tx_info->oam.type;
        p_raw_hdr->u1.oam.rx_oam = 0;
         /*SetMsPacketHeader(V, u1_oam_entropyLabelExist_f, p_raw_hdr, FALSE);*/
         /*SetMsPacketHeader(V, u1_oam_isEloopPkt_f, p_raw_hdr, FALSE);*/
         p_raw_hdr->u1.oam.dm_en = CTC_FLAG_ISSET(p_tx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_DM)? 1 : 0;
         if (p_raw_hdr->u1.oam.dm_en && (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_NHID_VALID)))
         {
             CTC_ERROR_RETURN(sys_usw_nh_set_ts_edit_en(lchip, p_tx_info->nhid, TRUE));
         }
        p_raw_hdr->u1.oam.rxtx_fcl_l_or_dm_offset = CTC_FLAG_ISSET(p_tx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_DM)?
            p_tx_info->oam.dm_ts_offset: 0;

        if (CTC_FLAG_ISSET(p_tx_info->oam.flags, CTC_PKT_OAM_FLAG_LINK_OAM))
        {
            p_raw_hdr->u1.oam.link_oam = 1;
        }

        /* TPOAM Y.1731 Section need not append 13 label */
        if (CTC_OAM_TYPE_ACH == p_tx_info->oam.type)
        {
            p_raw_hdr->u1.oam.mep_index |= (1<<5);
            /* only ACH encapsulation need to change packet_type */
            if (CTC_FLAG_ISSET(p_tx_info->oam.flags, CTC_PKT_OAM_FLAG_HAS_MPLS_GAL))
            {
                p_raw_hdr->u1.oam.mep_index |= (1<<4);
                packet_type = CTC_PARSER_PKT_TYPE_MPLS;
            }
            else
            {
                packet_type = CTC_PARSER_PKT_TYPE_RESERVED;
            }
            p_raw_hdr->packet_type = packet_type;
        }

        /* set for UP MEP */
        if (CTC_FLAG_ISSET(p_tx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_UP_MEP))
        {
            p_raw_hdr->u1.oam.is_up = 1;
            gchip = CTC_MAP_GPORT_TO_GCHIP(p_tx_info->dest_gport);
            lport = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_tx_info->dest_gport);
            /* dest_map is ILOOP */
            dest_map = SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_ILOOP_ID);
            dest_map = dest_map | (lport&0x100);/*SliceId*/
            p_raw_hdr->dest_map = dest_map;

            next_hop_ptr = SYS_PACKET_ENCAP_LOOP_NHPTR(lport, (p_tx_info->ttl != 0));
            p_raw_hdr->next_hop_ptr_18_0_0 = next_hop_ptr&0x1;
            p_raw_hdr->next_hop_ptr_18_17_1 = (next_hop_ptr>>1)&0x1FFFF;

            /* src vlan_ptr is vlan_ptr by vid */
            /*sys_usw_vlan_get_vlan_ptr(lchip, p_tx_info->oam.vid, &vlan_ptr);*/
            vlan_ptr = p_usw_pkt_master[lchip]->tx_hdr_info.vlanptr[p_tx_info->oam.vid];
            p_raw_hdr->src_vlan_ptr_14_0_0 = vlan_ptr&0x1;
            p_raw_hdr->src_vlan_ptr_14_13_1 = (vlan_ptr>>1)&0x1FFF;
        }

        /* set bypass MIP port */
        if (CTC_FLAG_ISSET(p_tx_info->oam.flags, CTC_PKT_OAM_FLAG_TX_MIP_TUNNEL))
        {
            /* bypass OAM packet to MIP configured port; otherwise, packet will send to CPU again */
            p_raw_hdr->u1.oam.oam_type = CTC_OAM_TYPE_NONE;
            p_raw_hdr->oam_tunnel_en = 1;
        }
    }

    if (CTC_PKT_OPER_PTP == p_tx_info->oper_type)
    {
        /* 7. get PTP */
        /*  DM Timestamp Bits Mapping
            Timestamp               Field Name          BIT Width   BIT Base
            dmTimestamp[36:5]       timestamp_36_5           32          5
            dmTimestamp[4:0]      u1_ptp_timestamp_4_0  5          0
            dmTimestamp[61:37]      u1_ptp_timestamp_61_37  25          37
         */
        _sys_usw_packet_ts_to_bit62(lchip, TRUE, &p_tx_info->ptp.ts, &ts_61_0);

        if ((CTC_PTP_CORRECTION == p_tx_info->ptp.oper) && (!(CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_PTP_TS_PRECISION))))
        {
            /*sal_memset(&ptp_offset_adjust, 0, sizeof(ptp_offset_adjust));
            cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust));

            GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
            GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);*/
#if (FEATURE_MODE == 0)
            if(p_usw_pkt_master[lchip]->tx_hdr_info.sync_hw_mode)
            {
                uint32 cmd = 0;
                TsEngineOffsetAdj_m ptp_offset_adjust;
                SYS_EUNIT_HW_LOCK(lchip, 2, 0);
                cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust));
                SYS_EUNIT_HW_UNLOCK(lchip, 2, 0);
                GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
                GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);
            }
            else
#endif
            {
                offset_ns = p_usw_pkt_master[lchip]->tx_hdr_info.offset_ns;
                offset_s = p_usw_pkt_master[lchip]->tx_hdr_info.offset_s;
            }
            offset = offset_s * 1000000000ULL + offset_ns;
            if (ts_61_0 >= offset)
            {
                ts_61_0 = ts_61_0 -offset;
            }
            else
            {
                return CTC_E_INVALID_PARAM;
            }
        }

        ts_4_0 = ts_61_0 & 0x1FULL;
        ts_36_5 = (ts_61_0 >> 5) & 0xFFFFFFFFULL;
        ts_61_37 = (ts_61_0 >> 37) & 0x01FFFFFFULL;
        p_raw_hdr->timestamp_36_5_29_0 = ts_36_5&0x3FFFFFFF;
        p_raw_hdr->timestamp_36_5_31_30 = (ts_36_5>>30)&0x3;
        p_raw_hdr->u1.ptp.timestamp_4_0 = ts_4_0&0x1F;
        p_raw_hdr->u1.ptp.timestamp_61_37_25_3_0 = ts_61_37&0xF;
        p_raw_hdr->u1.ptp.timestamp_61_37_25_24_4 = (ts_61_37>>4)&0x1FFFFF;
        p_raw_hdr->u1.ptp.ptp_apply_egress_asymmetry_delay = p_tx_info->ptp.delay_asymmetry_en;

        switch (p_tx_info->ptp.oper)
        {
            case CTC_PTP_CAPTURE_ONLY:
            {
                p_raw_hdr->u1.ptp.ptp_capture_timestamp = 1;
                p_raw_hdr->u1.ptp.ptp_sequence_id = p_tx_info->ptp.seq_id;
                p_raw_hdr->u1.ptp.ptp_msg_type = p_tx_info->ptp.msg_type;
                break;
            }
            case CTC_PTP_REPLACE_ONLY:
            {
                p_raw_hdr->u1.ptp.ptp_replace_timestamp = 1;
                p_raw_hdr->u1.ptp.ptp_offset = p_tx_info->ptp.ts_offset;
                break;
            }
            case CTC_PTP_NULL_OPERATION:
            {
                /* do nothing */
                break;
            }
            case CTC_PTP_CORRECTION:
            {
                /*SetMsPacketHeader(V, u1_ptp_ptpReplaceTimestamp_f, p_raw_hdr, TRUE);*/
                p_raw_hdr->u1.ptp.ptp_update_residence_time = 1;
                p_raw_hdr->u1.ptp.ptp_offset = p_tx_info->ptp.ts_offset;
                break;
            }
            default:
            {
                return CTC_E_INVALID_PARAM;
            }
        }
    }

    if (CTC_PKT_OPER_C2C == p_tx_info->oper_type)
    {
        uint8  sub_queue_id = 0;
        uint8  grp_id       = 0;
        p_raw_hdr->logic_src_port_15_8_0 = 0; /*logic port mean c2c extend group id*/
        p_raw_hdr->logic_src_port_15_14_9 = 0;
        p_raw_hdr->bypass_ingress_edit = 1;
        if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_MCAST))
        {
            p_raw_hdr->u1.c2c.c2c_check_disable = 1;
        }

        if (!CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_MCAST) &&
            !CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_INGRESS_MODE))
        {
            if (!sys_usw_chip_is_local(lchip, SYS_DECODE_DESTMAP_GCHIP(dest_map)) ||
                 CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_ASSIGN_DEST_PORT))
            {
                /*CTC_ERROR_RETURN(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_C2C_PKT, &sub_queue_id));*/
                sub_queue_id = p_usw_pkt_master[lchip]->tx_hdr_info.c2c_sub_queue_id;
                grp_id = (sub_queue_id / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM)) + (priority/8);
                /*to cpu based on prio*/
                dest_map = SYS_ENCODE_EXCP_DESTMAP_GRP(gchip, grp_id);
                dest_map |= 0x10;
            }
            else
            {
                p_raw_hdr->u1.c2c.neighbor_discover_packet = 1;
                p_raw_hdr->u1.c2c.c2c_check_disable = 1;
                p_raw_hdr->next_hop_ptr_18_0_0 = CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_C2C_PKT, 0)&0x1;
                p_raw_hdr->next_hop_ptr_18_17_1 = (CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_C2C_PKT, 0)>>1)&0x1FFFF;
                p_raw_hdr->bypass_ingress_edit = 1;
            }
        }
    }
    if (CTC_FLAG_ISSET(p_tx_info->flags, CTC_PKT_FLAG_FLEXE))
    {
        sys_dmps_flexe_phy_inst_t phy_inst;

        phy_inst.serdes_id = p_tx_info->flexe.serdes_id;
        phy_inst.instance_id = 0;
        dmps_port_info.gport = gport;
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_DP_ASICINST_ID, (void*)&phy_inst));
        dest_map = ((phy_inst.dp_id & 0x1) << 5) | ((phy_inst.asic_inst_id[0] &7) << 2) | (p_tx_info->flexe.chan_type &3);
    }
    p_raw_hdr->prio_4_1_0 = priority&0x3;
    p_raw_hdr->prio_4_3_2 = (priority>>2)&0x3;
    p_raw_hdr->dest_map = dest_map;

#if (0 == SDK_WORK_PLATFORM)
    sys_usw_swap32(tmp_raw_hdr, SYS_USW_PKT_HEADER_LEN/sizeof(uint32), FALSE);
    sal_memcpy(p_raw_hdr_net, tmp_raw_hdr, SYS_USW_PKT_HEADER_LEN);
#else
    {
        uint8 loop = 0;
        uint32 bheader[48/4] = {0}; /*hdr+tail*/
        do
        {
            sys_usw_byte_reverse_copy((uint8*)&bheader[loop], (uint8*)(tmp_raw_hdr+loop), 4);
            loop++;
        }while(loop < SYS_USW_PKT_HEADER_LEN/sizeof(uint32));
        sal_memcpy((uint8*)p_raw_hdr_net, (uint8*)bheader, SYS_USW_PKT_HEADER_LEN);
    }
#endif
    return CTC_E_NONE;
}

int32
sys_tmm_packet_rawhdr_to_rxinfo(uint8 lchip, uint32* p_raw_hdr_net, ctc_pkt_rx_t* p_pkt_rx)
{
    ms_packet_header_tmm_t* p_raw_hdr = NULL;
    ms_packet_header_tmm_tail_t* p_raw_hdr_tail = NULL;
    uint32 dest_map                = 0;
    uint32 ts_36_5 = 0;
    uint32 ts_4_0 = 0;
    uint32 ts_61_37 = 0;
    uint64 ts_61_0 = 0;
    uint32 src_port                = 0;
    uint32 next_hop_ptr            = 0;
    ctc_pkt_info_t* p_rx_info      = NULL;
    uint32 value = 0;
    uint8 gchip_id = 0;
    uint8 i2e_src_cid_valid = 0;
    uint8 field_val = 0;
    uint32 offset_ns = 0;
    uint32 offset_s = 0;
#if (FEATURE_MODE == 0)
    uint32 cmd = 0;
#endif
    uint16 vlan_ptr = 0;
    uint16 lport = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    p_rx_info = &p_pkt_rx->rx_info;
    CTC_ERROR_RETURN(sys_usw_swap32((uint32*)p_raw_hdr_net, SYS_USW_PKT_HEADER_LEN / sizeof(uint32), FALSE));

    p_raw_hdr_tail = (ms_packet_header_tmm_tail_t*)(p_raw_hdr_net + 10);
    sal_memset(p_rx_info, 0, sizeof(ctc_pkt_info_t));
    p_raw_hdr = (ms_packet_header_tmm_t*)p_raw_hdr_net;

    if (p_pkt_rx->dma_chan == SYS_DMA_FLEXE_RX_RING)
    {
        sys_dmps_flexe_phy_inst_t phy_inst;
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_FLEXE);
        p_rx_info->reason = CTC_PKT_CPU_REASON_FLEXE_PDU;
        ts_36_5 = p_raw_hdr->timestamp_36_5_29_0 | (p_raw_hdr->timestamp_36_5_31_30<<30) ;/* always carry timestamp regardless of pkt type */
        ts_4_0 = p_raw_hdr->u1.ptp.timestamp_4_0;
        ts_61_37 = p_raw_hdr->u1.ptp.timestamp_61_37_25_3_0 | (p_raw_hdr->u1.ptp.timestamp_61_37_25_24_4<<4);
        ts_61_0 = (((uint64)ts_4_0) << 0) | (((uint64)ts_36_5) << 5) | (((uint64)ts_61_37) << 37);

        _sys_usw_packet_bit62_to_ts(lchip, FALSE, ts_61_0, &p_rx_info->ptp.ts);
        src_port = p_raw_hdr->source_port_16_0_0 | (p_raw_hdr->source_port_16_15_1 << 1);

        phy_inst.asic_inst_id[0] = (src_port >> 2) & 0x7;
        phy_inst.dp_id = (src_port >> 5) & 0x1;
        dmps_port_info.gport = 0;
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_PHY_INST_ID, (void*)&phy_inst));
        p_rx_info->flexe.chan_type = src_port & 0x3;
        p_rx_info->flexe.serdes_id = phy_inst.serdes_id;
        return CTC_E_NONE;
    }
    /* Must be inited */
    p_rx_info->packet_type    = p_raw_hdr->packet_type;
    p_rx_info->oper_type      = p_raw_hdr->operation_type;
    p_rx_info->priority       = (p_raw_hdr->prio_4_3_2<<2)|p_raw_hdr->prio_4_1_0;
    p_rx_info->color          = p_raw_hdr->color;
    p_rx_info->src_cos        = p_raw_hdr->src_stag_cos;
    p_rx_info->fid            = p_raw_hdr->fid;
    p_rx_info->payload_offset = p_raw_hdr->packet_offset;
    p_rx_info->ttl            = p_raw_hdr->ttl;
    p_rx_info->is_critical    = p_raw_hdr->critical_packet;
    p_rx_info->logic_src_port = (p_raw_hdr->logic_src_port_15_14_9<<9)|p_raw_hdr->logic_src_port_15_8_0;
    p_rx_info->lport          = p_raw_hdr->local_phy_port;
#if 0
    /* Below is int decap */
    p_rx_info->int_info.igs_timestamp    = GetMsPacketHeader(V, timestamp_36_5_f, p_raw_hdr);
    p_rx_info->int_info.local_src_port   = GetMsPacketHeader(V, u1_intdata_srcLocalPhyPort_f, p_raw_hdr);
    //p_rx_info->int_info.queue_grp_offset = 0;    /*__TODO__ for spec bug*/
    p_rx_info->int_info.queue_id         = 0;    /*__TODO__ for spec bug*/
    p_rx_info->int_info.queue_cnt        = GetMsPacketHeader(V, u1_intdata_queueDepth_f, p_raw_hdr);
    lantency_20_31                   = GetMsPacketHeader(V, srcSvlanId_f, p_raw_hdr);
    p_rx_info->int_info.hop_lantency     = (lantency_20_31 << 20) + GetMsPacketHeader(V, u1_intdata_latency_0_19_f, p_raw_hdr);
    p_rx_info->int_info.egs_port_load    = GetMsPacketHeader(V, u1_intdata_intDestPortLoad_f, p_raw_hdr);
    p_rx_info->int_info.local_dst_port   = p_rx_info->lport;
    p_rx_info->int_info.int_session      = GetMsPacketHeaderTail(V, u_gCpu_cpuReserved_f, p_raw_hdr_tail);
#endif
    if (!p_raw_hdr->mac_known)
    {
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_UNKOWN_MACDA);
    }

    if (CTC_PKT_OPER_NORMAL == p_rx_info->oper_type)
    {
        if (p_raw_hdr->u1.normal.metadata_type == 0x01)
        {
            /*meta*/
            p_rx_info->meta_data = (p_raw_hdr->u1.normal.metadata_15_14_10<<10)|p_raw_hdr->u1.normal.metadata_15_9_0;
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_METADATA_VALID);
        }
        else if (p_raw_hdr->u1.normal.metadata_type == 3)
        {
            /*vrfid*/
            p_rx_info->vrfid= (p_raw_hdr->u1.normal.metadata_15_14_10<<10)|p_raw_hdr->u1.normal.metadata_15_9_0;
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_VRFID_VALID);
        }
        else if (p_raw_hdr->u1.normal.metadata_type == 0 && (!MCHIP_FEATURE_EN(lchip, CTC_FEATURE_SRV6)))
        {
            /*efd flow id*/
            p_rx_info->efd_flow_id = ((p_raw_hdr->u1.normal.metadata_15_14_10 & 0xf)<<10)|p_raw_hdr->u1.normal.metadata_15_9_0;
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_EFD_FLOW_ID_VALID);
        }
    }
    src_port = (p_raw_hdr->source_port_16_15_1<<1)|p_raw_hdr->source_port_16_0_0;
    p_rx_info->src_chip = SYS_DRV_GPORT_TO_GCHIP(src_port);
    if (p_raw_hdr->from_lag)
    {
        p_rx_info->src_port = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(CTC_LINKAGG_CHIPID, SYS_DRV_GPORT_TO_LPORT(src_port));
    }
    else
    {
        p_rx_info->src_port = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(src_port);
    }

    gchip_id = p_rx_info->src_chip;
    if(sys_usw_chip_is_local(lchip, gchip_id) && !CTC_IS_LINKAGG_PORT(p_rx_info->src_port))
    {
        sys_usw_port_api_get_local_phy_port(lchip, p_rx_info->src_port, &value);
        if (SYS_INVALID_LOCAL_PHY_PORT != value)
        {
            p_rx_info->src_port = CTC_MAP_LPORT_TO_GPORT(p_rx_info->src_chip, value);
        }
    }
    if (p_rx_info->lport >= MCHIP_CAP(SYS_CAP_INTERNAL_PORT_START))
    {
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_INTERNAl_PORT);
    }

    /* RX Reason from next_hop_ptr */
    next_hop_ptr = (p_raw_hdr->next_hop_ptr_18_17_1<<1)|p_raw_hdr->next_hop_ptr_18_0_0;
    p_rx_info->reason = CTC_PKT_CPU_REASON_GET_BY_NHPTR(next_hop_ptr);
    if ((p_rx_info->reason == CTC_PKT_CPU_REASON_DIAG_DISCARD_PKT)
        && (next_hop_ptr & 0x1))
    {
        /* EPE Discard */
        if (p_usw_pkt_master[lchip]->tx_hdr_info.epe_discard_en)
        {
            /*ttl means discard type, set bit6 means EPE discard type*/
            p_rx_info->ttl |= 0x40;
        }
    }
    else if (p_rx_info->reason == CTC_PKT_CPU_REASON_NPM_IM_DELAY)
    {
        p_rx_info->efd_flow_id = ((p_raw_hdr->u1.normal.ecmp_hash&0xF)<<16)|(((p_raw_hdr_tail->service_id)&0xFF)<<8)|p_raw_hdr->u1.normal.i2e_src_cid;
    }
    /*EFM src port*/
    if (SYS_DRV_GPORT_TO_LPORT(src_port) >= MCHIP_CAP(SYS_CAP_INTERNAL_PORT_START)
        && (sys_usw_chip_is_local(lchip, gchip_id) && !CTC_IS_LINKAGG_PORT(p_rx_info->src_port)))
    {
        lport = SYS_DRV_GPORT_TO_LPORT(src_port);
        sys_usw_port_api_lport_convert(lchip, SYS_DRV_GPORT_TO_LPORT(src_port), &lport);
        p_rx_info->src_port = CTC_MAP_LPORT_TO_GPORT(gchip_id, lport);
    }

    /* SubQueId or raw dest_gport*/
    dest_map = p_raw_hdr->dest_map;
    if(SYS_DESTMAP_IS_CPU(dest_map))
    {
        p_rx_info->dest_gport = SYS_DESTMAP_IS_GRP(dest_map) ? ((dest_map & 0xF) * MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) + p_rx_info->priority/2) : (dest_map&0xFF);
    }
    else
    {
        p_rx_info->dest_gport = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(p_raw_hdr->dest_map);
    }
    if (SYS_DESTMAP_IS_MCAST(p_raw_hdr->dest_map))
    {
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_MCAST);
        p_rx_info->dest_group_id = p_raw_hdr->dest_map&0xFFFF;
    }
    if (DRV_FROM_TMM(lchip) && SYS_DESTMAP_IS_CPU_MAC(dest_map))
    {
        uint8 gchip = 0;
        uint32 destmap_cpu_mac = 0;
        destmap_cpu_mac = SYS_DESTMAP_TO_CPU_MAC(dest_map);
        sys_usw_get_gchip_id(lchip, &gchip);
        p_rx_info->dest_gport = CTC_MAP_LPORT_TO_GPORT(gchip, destmap_cpu_mac) | (CTC_GPORT_TYPE_CPU_MAC << CTC_TYPE_PORT_OFFSET);
    }

    /* Source svlan */
    p_rx_info->src_svid = p_raw_hdr->src_svlan_id;
    vlan_ptr = (p_raw_hdr->src_vlan_ptr_14_13_1<<1)|p_raw_hdr->src_vlan_ptr_14_0_0;
    if((p_rx_info->src_svid == 0) && (vlan_ptr < 4096))
    {
        p_rx_info->src_svid = vlan_ptr;
    }

    if (p_rx_info->src_svid)
    {
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_SRC_SVID_VALID);
    }

    /* Source cvlan */
    if (CTC_PKT_OPER_NORMAL == p_rx_info->oper_type)
    {
        p_rx_info->src_cvid = p_raw_hdr->u1.normal.src_cvlan_id;
        if (p_rx_info->src_cvid)
        {
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_SRC_CVID_VALID);
        }
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_ENCRYPTED);
    }

    if (p_raw_hdr->svlan_tag_operation_valid)
    {
        field_val = p_raw_hdr->stag_action;
        if (field_val == DRV_CONST(DRV_VTAGACTIONTYPE_MODIFY))
        {
            p_rx_info->stag_op = CTC_VLAN_TAG_OP_REP;
        }
        else if (field_val == DRV_CONST(DRV_VTAGACTIONTYPE_ADD))
        {
            p_rx_info->stag_op = CTC_VLAN_TAG_OP_ADD;
        }
        else if (field_val == DRV_CONST(DRV_VTAGACTIONTYPE_DELETE))
        {
            p_rx_info->stag_op = CTC_VLAN_TAG_OP_DEL;
        }
    }

    if ((CTC_PKT_OPER_NORMAL == p_rx_info->oper_type) && p_raw_hdr->u1.normal.cvlan_tag_operation_valid)
    {
        field_val = p_raw_hdr->u1.normal.ctag_action;
        if (field_val == DRV_CONST(DRV_VTAGACTIONTYPE_MODIFY))
        {
            p_rx_info->ctag_op = CTC_VLAN_TAG_OP_REP;
        }
        else if (field_val == DRV_CONST(DRV_VTAGACTIONTYPE_ADD))
        {
            p_rx_info->ctag_op = CTC_VLAN_TAG_OP_ADD;
        }
        else if (field_val == DRV_CONST(DRV_VTAGACTIONTYPE_DELETE))
        {
            p_rx_info->ctag_op = CTC_VLAN_TAG_OP_DEL;
        }
    }

    i2e_src_cid_valid = p_raw_hdr->u1.normal.i2e_src_cid_valid;
    if (i2e_src_cid_valid && (CTC_PKT_OPER_OAM != p_rx_info->oper_type) && (CTC_PKT_CPU_REASON_NPM_IM_DELAY != p_rx_info->reason) && (1 != p_rx_info->oper_type))
    {
        p_rx_info->cid = ((MCHIP_CAP(SYS_CAP_ACL_MAX_CID_VALUE)==65535)?((p_raw_hdr_tail->service_id&0xFF)<<8):0) | p_raw_hdr->u1.normal.i2e_src_cid;
    }

    /* Timestamp */
    ts_36_5 = (p_raw_hdr->timestamp_36_5_31_30<<30)|p_raw_hdr->timestamp_36_5_29_0;

    if (CTC_PKT_OPER_PTP == p_rx_info->oper_type)
    {
        ts_4_0 = p_raw_hdr->u1.ptp.timestamp_4_0;
        ts_61_37 = (p_raw_hdr->u1.ptp.timestamp_61_37_25_24_4<<4)|p_raw_hdr->u1.ptp.timestamp_61_37_25_3_0;

        ts_61_0 = (((uint64)ts_4_0) << 0) | (((uint64)ts_36_5) << 5) | (((uint64)ts_61_37) << 37);
#if (FEATURE_MODE == 0)
        if(p_usw_pkt_master[lchip]->tx_hdr_info.sync_hw_mode)
        {
            TsEngineOffsetAdj_m ptp_offset_adjust;
            SYS_EUNIT_HW_LOCK(lchip, 2, 0);
            cmd = DRV_IOR(TsEngineOffsetAdj_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ptp_offset_adjust));
            SYS_EUNIT_HW_UNLOCK(lchip, 2, 0);
            GetTsEngineOffsetAdj(A, offsetNs_f, &ptp_offset_adjust, &offset_ns);
            GetTsEngineOffsetAdj(A, offsetSecond_f, &ptp_offset_adjust, &offset_s);
        }
        else
#endif
        {
            offset_ns = p_usw_pkt_master[lchip]->tx_hdr_info.offset_ns;
            offset_s = p_usw_pkt_master[lchip]->tx_hdr_info.offset_s;
        }
        ts_61_0 = ts_61_0 + offset_s * 1000000000ULL + offset_ns;
        _sys_usw_packet_bit62_to_ts(lchip, TRUE, ts_61_0, &p_rx_info->ptp.ts);
    }
#ifdef  CTC_PKT_EN_TS
    else
    {
        CTC_ERROR_RETURN(_sys_usw_packet_recover_timestamp(lchip, ts_36_5, &ts_61_0));
        offset_ns = p_usw_pkt_master[lchip]->tx_hdr_info.offset_ns;
        offset_s = p_usw_pkt_master[lchip]->tx_hdr_info.offset_s;
        ts_61_0 = ts_61_0 + offset_s * 1000000000ULL + offset_ns;
        _sys_usw_packet_bit62_to_ts(lchip, TRUE, ts_61_0, &p_rx_info->ptp.ts);
    }
#endif

    /* OAM */
    if (CTC_PKT_OPER_OAM == p_rx_info->oper_type)
    {
        p_rx_info->oam.type = p_raw_hdr->u1.oam.oam_type;
        p_rx_info->oam.mep_index = p_raw_hdr->u1.oam.mep_index;

        if (p_raw_hdr->u1.oam.is_up)
        {
            CTC_SET_FLAG(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_UP_MEP);
        }

        if (p_raw_hdr->u1.oam.lm_received_packet)
        {
            CTC_SET_FLAG(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_LM);
        }
        else if (p_raw_hdr->u1.oam.rx_fcb&SYS_PKT_OAM_VRF_VALID)
        {
            p_rx_info->vrfid = p_raw_hdr->u1.oam.rx_fcb&0x3FFF;
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_VRFID_VALID);
        }

        if (p_raw_hdr->u1.oam.link_oam)
        {
            CTC_SET_FLAG(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_LINK_OAM);
        }

        if (p_raw_hdr->u1.oam.dm_en)
        {
            CTC_SET_FLAG(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_DM);
        }

        if (p_raw_hdr->u1.oam.gal_exist)
        {
            CTC_SET_FLAG(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_HAS_MPLS_GAL);
        }

        field_val = p_raw_hdr->u1.oam.mip_en;
        if (field_val)
        {
            CTC_SET_FLAG(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_MIP);
        }

        /* get timestamp offset in bytes for DM */
        if (CTC_FLAG_ISSET(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_DM))
        {
            /*  DM Timestamp Bits Mapping
                Timestamp               Field Name          BIT Width   BIT Base
                dmTimestamp[37:0]       timestamp           38          0
                dmTimestamp[61:38]      u3_other_timestamp  24          38
             */
 #if 0
            GetMsPacketHeader(A, timestamp_f, p_raw_hdr, &ts_37_0_tmp);
            ts_37_0 = ts_37_0_tmp[1];
            ts_37_0 <<= 32;
            ts_37_0 |= ts_37_0_tmp[0];

            ts_61_38 = GetMsPacketHeader(V, u3_other_timestamp_f, p_raw_hdr);

            ts_61_0 = ((uint64)(ts_37_0) << 0)
                    | ((uint64)(ts_61_38) << 38);
            ns_only_format = FALSE;
            _sys_usw_packet_bit62_to_ts(lchip, ns_only_format, ts_61_0, &p_rx_info->oam.dm_ts);
#endif
        }

        if (CTC_FLAG_ISSET(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_LM))
        {
            p_rx_info->oam.lm_fcl = p_raw_hdr->u1.oam.rxtx_fcl_h;
            p_rx_info->oam.lm_fcl = (p_rx_info->oam.lm_fcl << 8) + p_raw_hdr->u1.oam.rxtx_fcl_l_or_dm_offset;
            p_rx_info->oam.lm_fcl |= ((uint64)p_raw_hdr->u1.oam.rx_fcb<<32);
        }

        /* get svid from vlan_ptr for Up MEP/Up MIP */
        if (CTC_FLAG_ISSET(p_rx_info->oam.flags, CTC_PKT_OAM_FLAG_IS_UP_MEP))
        {
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_SRC_SVID_VALID);
            p_rx_info->src_svid = (p_raw_hdr->src_vlan_ptr_14_13_1<<1)|p_raw_hdr->src_vlan_ptr_14_0_0;
        }
    }

    if (p_usw_pkt_master[lchip]->tx_hdr_info.stk_en)
    {
    if (CTC_PKT_OPER_C2C == p_rx_info->oper_type)
    {
        uint16  sub_queue_id = 0;
        /* Stacking*/
        p_rx_info->reason       = CTC_PKT_CPU_REASON_C2C_PKT;
        p_rx_info->stacking_src_port     = p_raw_hdr->u1.c2c.stacking_src_port;
        p_rx_info->stacking_src_port     = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(p_rx_info->stacking_src_port);

        if (CTC_FLAG_ISSET(p_rx_info->flags, CTC_PKT_FLAG_MCAST))
        {
            CTC_UNSET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_MCAST);
            p_rx_info->dest_group_id = 0;
        }
        p_rx_info->vrfid = 0;

        if (p_raw_hdr->u1.c2c.neighbor_discover_packet)
        {
            p_rx_info->dest_gport = (dest_map & 0xF) * MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) + (p_rx_info->priority/2);
        }
        else
        {
           p_rx_info->dest_gport = (dest_map & 0xF) * MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM) + (p_rx_info->priority%8);
        }

        CTC_ERROR_RETURN(sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_C2C_PKT, &sub_queue_id));
        if(DRV_IS_DUET2(lchip))
        {
            p_rx_info->priority = (p_rx_info->dest_gport > sub_queue_id) ? (p_rx_info->dest_gport - sub_queue_id) : 0;
        }
    }

    if (p_rx_info->reason == CTC_PKT_CPU_REASON_MONITOR_BUFFER_LOG)
    {
        if (p_raw_hdr->src_stag_cfi)
        {
            CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_BUFFER_VICTIM_PKT);
        }
    }

    if (p_raw_hdr->from_fabric)
    {
        uint8 legacy_en = 0;
        uint16 cloud_hdr_len = 0;
        uint16 extHeaderLen = 0;
        uint16 stk_hdr_len = 0;
        uint32 stk_basic[4] = {0};
        uint8  packet_rx_header_en = 0;
        uint16 local_phy_port =0;
        uint8 gchip_id = 0;
        CFHeaderBasic_m* p_stk_header = NULL;
        uint8 oper_type = 0;

        local_phy_port = p_raw_hdr->local_phy_port;
        sys_usw_get_gchip_id(lchip, &gchip_id);

        CTC_ERROR_RETURN(SYS_CB(SYS_CB_STK_GET_STKHDR_VER, lchip, &legacy_en));
        packet_rx_header_en = (p_usw_pkt_master[lchip]->tx_hdr_info.cloud_hdr_len[local_phy_port] == 0xff)?0:1;

        if (packet_rx_header_en)
        {
            cloud_hdr_len = p_usw_pkt_master[lchip]->tx_hdr_info.cloud_hdr_len[local_phy_port];
            if (!legacy_en)
            {
                /*Using CFlex header, get from stacking module only means Cloud Header Length*/
                p_stk_header = (CFHeaderBasic_m*)(p_pkt_rx->pkt_buf[0].data + SYS_USW_PKT_HEADER_LEN + p_pkt_rx->eth_hdr_len + cloud_hdr_len);
                CTC_ERROR_RETURN(sys_usw_dword_reverse_copy((uint32*)stk_basic, (uint32*)p_stk_header, 4));
                CTC_ERROR_RETURN(sys_usw_swap32((uint32*)stk_basic, 4, FALSE));
                extHeaderLen = GetCFHeaderBasic(V, extHeaderLen_f, (uint32*)stk_basic);
                stk_hdr_len = (16 + (extHeaderLen << 3));
            }
            else
            {
                stk_hdr_len = SYS_PACKET_BASIC_STACKING_HEADER_LEN;
            }

            p_pkt_rx->stk_hdr_len = cloud_hdr_len + stk_hdr_len;
        }

        if (p_usw_pkt_master[lchip]->tx_hdr_info.stk_inner_brg_en)
        {
            p_raw_hdr = (ms_packet_header_tmm_t*)(p_pkt_rx->pkt_buf[0].data + SYS_USW_PKT_HEADER_LEN + p_pkt_rx->eth_hdr_len + p_pkt_rx->stk_hdr_len);
            CTC_ERROR_RETURN(sys_usw_swap32((uint32*)p_raw_hdr, SYS_USW_PKT_HEADER_LEN / 4, FALSE));
            oper_type  = p_raw_hdr->operation_type;
            if ((CTC_PKT_OPER_NORMAL == oper_type) && (p_raw_hdr->u1.normal.metadata_type == 3))
            {
                /*vrfid*/
                p_rx_info->vrfid= (p_raw_hdr->u1.normal.metadata_15_14_10<<10)|p_raw_hdr->u1.normal.metadata_15_9_0;
                CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_VRFID_VALID);
            }
            p_pkt_rx->stk_hdr_len += SYS_USW_PKT_HEADER_LEN;
        }
    }
    else if (CTC_PKT_OPER_OAM != p_rx_info->oper_type)
    {
        if (next_hop_ptr & SYS_PKT_EXCEP_FROM_SGMAC)
        {
            p_pkt_rx->stk_hdr_len = p_raw_hdr->packet_offset;
        }
#if 0
        uint8  packet_rx_header_en = 0;

        if (p_usw_pkt_master[lchip]->tx_hdr_info.hdr_tail_with_dst_port)
        {
            lport = SYS_DRV_GPORT_TO_LPORT((p_raw_hdr_tail->dest_port_16_15_8 << 8) | p_raw_hdr_tail->dest_port_16_7_0);
        }
        else if(!SYS_DESTMAP_IS_CPU(dest_map))
        {
            lport = CTC_MAP_GPORT_TO_LPORT(p_rx_info->dest_gport);/* raw dest port */
        }
        packet_rx_header_en = (p_usw_pkt_master[lchip]->tx_hdr_info.cloud_hdr_len[lport] == 0xff)?0:1;

        if (packet_rx_header_en)
        {
            uint8 legacy_en = 0;
            uint16 cloud_hdr_len = 0;
            uint16 extHeaderLen = 0;
            uint16 stk_hdr_len = 0;
            uint32 stk_basic[8] = {0};
            CFHeaderBasic_m* p_stk_header = NULL;
            PacketHeaderOuter_m* p_legacy_header = NULL;
            uint8 cflex_mode = 0;
            uint16 cflex_port = 0;
            uint32 gport = 0;
            uint32 port_type = 0;
            
            CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
            gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, lport);
            CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, gport, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
            if ((port_type == SYS_DMPS_NETWORK_PORT) || (port_type == SYS_DMPS_CPUMAC_NETWORK_PORT))
            {
                cflex_mode = p_usw_pkt_master[lchip]->tx_hdr_info.cflex_mode[lport];
                cflex_port = p_usw_pkt_master[lchip]->tx_hdr_info.cflex_dest_map & p_usw_pkt_master[lchip]->tx_hdr_info.cflex_dest_map_mask;
            }

            CTC_ERROR_RETURN(SYS_CB(SYS_CB_STK_GET_STKHDR_VER, lchip, &legacy_en));
            cloud_hdr_len = p_usw_pkt_master[lchip]->tx_hdr_info.cloud_hdr_len[lport];
            if (!legacy_en)
            {
                /*Using CFlex header, get from stacking module only means Cloud Header Length*/
                p_stk_header = (CFHeaderBasic_m*)(p_pkt_rx->pkt_buf[0].data + SYS_USW_PKT_HEADER_LEN + p_pkt_rx->eth_hdr_len + cloud_hdr_len);
                CTC_ERROR_RETURN(sys_usw_dword_reverse_copy((uint32*)stk_basic, (uint32*)p_stk_header, 4));
                CTC_ERROR_RETURN(sys_usw_swap32((uint32*)stk_basic, 4, FALSE));
                extHeaderLen = GetCFHeaderBasic(V, extHeaderLen_f, (uint32*)stk_basic);
                stk_hdr_len = (16 + (extHeaderLen << 3));
                if (cflex_mode == 1 || ((cflex_mode == 2) && ((GetCFHeaderBasic(V, destMap_f, (uint32*)stk_basic) &
                     p_usw_pkt_master[lchip]->tx_hdr_info.cflex_dest_map_mask) == cflex_port)))
                {
                    p_rx_info->src_port = GetCFHeaderBasic(V, sourcePort_f,(uint32*)stk_basic);
                    p_rx_info->src_chip = SYS_DRV_GPORT_TO_GCHIP(p_rx_info->src_port);
                    if (GetCFHeaderBasic(V, fromLag_f, (uint32*)stk_basic))
                    {
                        p_rx_info->src_port = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(CTC_LINKAGG_CHIPID, SYS_DRV_GPORT_TO_LPORT(p_rx_info->src_port));
                    }
                    else
                    {
                        p_rx_info->src_port = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(p_rx_info->src_port);
                    }
                }
            }
            else
            {
                p_legacy_header = (PacketHeaderOuter_m*)(p_pkt_rx->pkt_buf[0].data + SYS_USW_PKT_HEADER_LEN + p_pkt_rx->eth_hdr_len + cloud_hdr_len);
                CTC_ERROR_RETURN(sys_usw_dword_reverse_copy((uint32*)stk_basic, (uint32*)p_legacy_header, 8));
                CTC_ERROR_RETURN(sys_usw_swap32((uint32*)stk_basic, 8, FALSE));
                stk_hdr_len = SYS_PACKET_BASIC_STACKING_HEADER_LEN;
                if (cflex_mode == 1 || ((cflex_mode == 2) && ((GetPacketHeaderOuter(V, destMap_f, (uint32*)stk_basic) &
                        p_usw_pkt_master[lchip]->tx_hdr_info.cflex_dest_map_mask)== cflex_port)))
                {
                    p_rx_info->src_port = GetPacketHeaderOuter(V, sourcePort_f,(uint32*)stk_basic);
                    p_rx_info->src_chip = SYS_DRV_GPORT_TO_GCHIP(p_rx_info->src_port);
                    if (p_rx_info->src_chip == 0x1f)
                    {
                        p_rx_info->src_chip = (((p_rx_info->src_port>>6)&0x7)|(((p_rx_info->src_port>>14)&0x3) << 3));
                        p_rx_info->src_port = p_rx_info->src_port&0x3f;
                        p_rx_info->src_port = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(CTC_LINKAGG_CHIPID, SYS_DRV_GPORT_TO_LPORT((p_rx_info->src_port))); 
                    }
                    else
                    {
                        p_rx_info->src_port = SYS_MAP_DRV_GPORT_TO_CTC_GPORT(p_rx_info->src_port);
                    }
                }
            }
            p_pkt_rx->stk_hdr_len = cloud_hdr_len + stk_hdr_len;
        }
#endif
    }
    }

    if((0xFFFF != p_usw_pkt_master[lchip]->vlanptr_2_vrf[vlan_ptr]) && !CTC_FLAG_ISSET(p_rx_info->flags, CTC_PKT_FLAG_VRFID_VALID))
    {
        p_rx_info->vrfid =  p_usw_pkt_master[lchip]->vlanptr_2_vrf[vlan_ptr];
        CTC_SET_FLAG(p_rx_info->flags, CTC_PKT_FLAG_VRFID_VALID);
    }
    return CTC_E_NONE;
}

int32
sys_tmm_packet_encap_array(uint8 lchip, ctc_pkt_tx_t** p_pkt_tx_array, uint32 count)
{
    uint32 pkt_tx_idx = 0;
    ctc_pkt_tx_t* p_pkt_tx = NULL;
#ifndef CTC_PKT_DIS_BUF
    uint8 chan_idx = 0;
#endif

    SYS_PACKET_INIT_CHECK(lchip);

    do{
        p_pkt_tx = p_pkt_tx_array[pkt_tx_idx];
        if (0 == p_usw_pkt_master[lchip]->cfg.raw_mode_en)
        {
            p_pkt_tx->skb.head = p_pkt_tx->skb.data - SYS_USW_PKT_HEADER_LEN;
            p_pkt_tx->lchip = lchip;

            /*When chip init, must register the callback.*/
            CTC_ERROR_RETURN(sys_tmm_packet_txinfo_to_rawhdr(lchip, p_pkt_tx));
            p_usw_pkt_master[lchip]->stats.encap++;
        }
        else
        {
            p_pkt_tx->skb.head = p_pkt_tx->skb.data;
            p_pkt_tx->skb.pkt_hdr_len -= SYS_USW_PKT_HEADER_LEN;
        }

#ifndef CTC_PKT_DIS_BUF
        /*tx buf dump data store*/
        chan_idx = SYS_DMA_PACKET_TX1_CHAN_ID - SYS_DMA_PACKET_TX0_CHAN_ID;
        if ((p_usw_pkt_master[lchip]->cursor[CTC_EGRESS][chan_idx] < SYS_PKT_BUF_MAX) && (p_usw_pkt_master[lchip]->pkt_buf_en[CTC_EGRESS]== 1))
        {
            sys_pkt_tx_buf_t* p_tx_buf = NULL;
            uint8   buffer_pos = 0;
            uint8   is_pkt_found = 0;
            uint8   hdr_len = (p_pkt_tx->mode == CTC_PKT_MODE_DMA) ? SYS_USW_PKT_HEADER_LEN:(SYS_USW_PKT_HEADER_LEN+SYS_USW_PKT_CPUMAC_LEN);
            uint16   stored_len = (p_pkt_tx->skb.len +hdr_len)>SYS_PKT_BUF_PKT_LEN ? SYS_PKT_BUF_PKT_LEN:(p_pkt_tx->skb.len +hdr_len);
            p_tx_buf = (sys_pkt_tx_buf_t*)&p_usw_pkt_master[lchip]->tx_buf[chan_idx][SYS_PKT_BUF_MAX];

            sal_memset(p_tx_buf, 0, sizeof(sys_pkt_tx_buf_t));
            p_tx_buf->mode  = p_pkt_tx->mode;
            p_tx_buf->pkt_len = p_pkt_tx->skb.len+SYS_USW_PKT_HEADER_LEN;

            sal_time(&p_tx_buf->tm);
            sal_memcpy(&p_tx_buf->tx_info,&(p_pkt_tx->tx_info),sizeof(ctc_pkt_info_t));
            sal_memcpy(&p_tx_buf->pkt_data[0],p_pkt_tx->skb.head, stored_len);
            p_tx_buf->hash_seed = ctc_hash_caculate(stored_len-hdr_len, &p_tx_buf->pkt_data[hdr_len]);

            for (buffer_pos = 0; buffer_pos < SYS_PKT_BUF_MAX; buffer_pos++)
            {
                if ((p_tx_buf->hash_seed == p_usw_pkt_master[lchip]->tx_buf[chan_idx][buffer_pos].hash_seed)
                    && (p_tx_buf->pkt_len ==  p_usw_pkt_master[lchip]->tx_buf[chan_idx][buffer_pos].pkt_len))
                {
                    is_pkt_found = 1;
                    break;
                }
            }

            /*update buf data*/
            if (!is_pkt_found )
            {
                buffer_pos = p_usw_pkt_master[lchip]->cursor[CTC_EGRESS][chan_idx];
                if(buffer_pos < SYS_PKT_BUF_MAX)
                {
                    p_usw_pkt_master[lchip]->cursor[CTC_EGRESS][chan_idx]++;
                }
            }
            sal_memcpy(&p_usw_pkt_master[lchip]->tx_buf[chan_idx][buffer_pos] ,p_tx_buf , sizeof(sys_pkt_tx_buf_t));
        }
#endif

        if (CTC_FLAG_ISSET(p_pkt_tx->tx_info.flags, CTC_PKT_FLAG_MCAST))
        {
             p_usw_pkt_master[lchip]->stats.mc_tx++;
        }
        else
        {
             p_usw_pkt_master[lchip]->stats.uc_tx++;
        }
    }while(++pkt_tx_idx < count);

    return CTC_E_NONE;
}


#endif

